/**************************************************************************************
*  PWM.c
*
*  This file defines all native methods that have to be implemented to support
*  the class lpc2xxx/hw/RTC
*
*  Application developer should use the following functions to get access to
*  arrays and String object:
*       vmGetStringCount
*       vmGetStringArray
*       vmGetArraySize
*       vmGetArray
*  These functions are accessible via vm_config_t structure.
*
*  Native methods implementation
*  -----------------------------
*  Note that if the native method is NOT declared as static then param[0]
*  contains object's reference and must be skiped when accessing the native
*  method parameters.
**************************************************************************************
*
* This file is covered by the GNU GPL with the following exception:
*   As a special exception, the copyright holders of this library give you permission
*   to link this library with independent modules to produce an executable, regardless
*   of the license terms of these independent modules, and to copy and distribute the
*   resulting executable under terms of your choice, provided that you also meet, for
*   each linked independent module, the terms and conditions of the license of that
*   module. An independent module is a module which is not derived from or based on
*   this library. If you modify this library, you may extend this exception to your
*   version of the library, but you are not obligated to do so. If you do not wish
*   to do so, delete this exception statement from your version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL RTJ COMPUTING BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2000-2006 RTJ Computing Pty. Ltd. All rights reserved.
**************************************************************************************/
#include <lpc2xxx.h>
#include "startup/config.h"
#include "general.h"
#include "javavm.h"

extern vm_config_t vmconfig;

#define PWM1    2
#define PWM2    4
#define PWM3    8
#define PWM4    16
#define PWM5    32
#define PWM6    64

static uint32 duty[6] = { 0, 0, 0, 0, 0, 0 };
static uint32 freq;


/****************************************************************************
* Sets the PWM frequency.
****************************************************************************/
static void setFreq(uint32 freqHz)
{
    freq = ((CRYSTAL_FREQUENCY * PLL_FACTOR) / (VPBDIV_FACTOR * freqHz));
}

/****************************************************************************
* Sets the PWM frequency.
****************************************************************************/
static void setDuty(uint32 pwm, uint32 new_duty)
{
    uint32 d = (PWM_MR0 * new_duty) / 10000;
    if (pwm & PWM1)
        duty[0] = d;
    if (pwm & PWM2)
        duty[1] = d;
    if (pwm & PWM3)
        duty[2] = d;
    if (pwm & PWM4)
        duty[3] = d;
    if (pwm & PWM5)
        duty[4] = d;
    if (pwm & PWM6)
        duty[5] = d;
}

/****************************************************************************
* Applies the new PWM duty cycle.
****************************************************************************/
static void apply(int pwm)
{
    PWM_MR0 = freq;
    PWM_MR1 = duty[0];
    PWM_MR2 = duty[1];
    PWM_MR3 = duty[2];
    PWM_MR4 = duty[3];
    PWM_MR5 = duty[4];
    PWM_MR6 = duty[5];
    PWM_LER = pwm | 1;
}

/****************************************************************************
* Initialises the selected PWM output(s).
* On entry: param[0] - PWM output pins
*           param[1] - frequency (in Hz) of the PWM output
*
* Java prototype:
*   private static native void init0(int pwm, int freq);
*
****************************************************************************/
int16 lpc2xxx_hw_PWM_init0(int32 param[], int32 *retval)
{
    PWM_PR  = 0;                    // set prescale to 0
    PWM_MCR = 0x0002;               // counter resets on MR0 match (period time)
    setFreq(param[1]);
    setDuty(param[0], 0);
    apply(param[0]);
    PWM_PCR |= (param[0] << 8);     // enable PWM in single edge control mode
    PWM_TCR = 0x09;                 // enable PWM and Counter

    return NO_EXCEP;
}

/****************************************************************************
* Sets the new frequency for PWM.
* On entry: param[0] - new value for frequency
*
* Java prototype:
*  public static native void freq(int fq);
*
****************************************************************************/
int16 lpc2xxx_hw_PWM_freq(int32 param[], int32 *retval)
{
    setFreq(param[1]);
    return NO_EXCEP;
}

/****************************************************************************
* Get the current value from specified RTC date/time register.
* On entry: param[0] - PWM output pins
*           param[1] - new value for duty cycle
*
* Java prototype:
*   public static native void duty(int pwm, int dc);
*
****************************************************************************/
int16 lpc2xxx_hw_PWM_duty(int32 param[], int32 *retval)
{
    setDuty(param[0], param[1]);
    return NO_EXCEP;
}

/****************************************************************************
* Applies new duty cycle for the specified PWM channels.
* On entry: param[0] - PWM output pins
*
* Java prototype:
*   private static native void apply(int pwm);
*
****************************************************************************/
int16 lpc2xxx_hw_PWM_apply(int32 param[], int32 *retval)
{
    apply(param[0]);
    return NO_EXCEP;
}


